#include "centerwidget.h"
#include <QDebug>
#include <QMouseEvent>
#include <QKeyEvent>
#include<vector>
#include<cmath>
#include <Eigen/Core>
#include "element/point.h"
#include <QTimer>


CenterWidget::CenterWidget(QWidget *parent) : QOpenGLWidget(parent),VBO(QOpenGLBuffer::VertexBuffer), EBO(QOpenGLBuffer::IndexBuffer)
{

}

CenterWidget::~CenterWidget()
{
    delete camera;
    delete texture1;
}

void CenterWidget::setCenter(double x, double y, double z)
{
    camera->cameraCenter = {float(x), float(y), float(z)};
    camera->cameraPos={0,0,0};
}



unsigned int indices[] = {
    // 注意索引从0开始!
    // 此例的索引(0,1,2,3)就是顶点数组vertices的下标，
    // 这样可以由下标代表顶点组合成矩形

    0, 1, 3, // 第一个三角形
    1, 3, 2  // 第二个三角形
};

void CenterWidget::initializeGL()
{
    qDebug()<<"initializeGL";

    this->initializeOpenGLFunctions();
    glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
    glEnable(GL_DEPTH_TEST);

    float vertices[] = {
    //     ---- 位置 ----       ---- 颜色 ----     - 纹理坐标 -
         0.5f,  0.5f, 0.0f,   1.0f, 0.0f, 0.0f,   1.0f, 1.0f,   // 右上
         0.5f, -0.5f, 0.0f,   0.0f, 1.0f, 0.0f,   1.0f, 0.0f,   // 右下
        -0.5f, -0.5f, 0.0f,   0.0f, 0.0f, 1.0f,   0.0f, 0.0f,   // 左下
        -0.5f,  0.5f, 0.0f,   1.0f, 1.0f, 0.0f,   0.0f, 1.0f    // 左上
    };


    std::vector<Eigen::Vector3d> circlePoints;
    circlePoints.push_back({0 ,0 ,0});
    circlePoints.push_back({2 ,0 ,0});
    circlePoints.push_back({0 ,0.5 ,4});
    circlePoints.push_back({0 ,-0.5 ,-4});
//    circlePoints.push_back({-63.0107 ,-78.5967 ,117.593});
//    circlePoints.push_back({-68.3232 ,-94.7589, 118.732});
//    circlePoints.push_back({-64.7761 ,-83.969, 117.979});
//    circlePoints.push_back({-62.2278 ,-76.2572, 117.451});
//    circlePoints.push_back({-60.9577 ,-72.4021, 117.161});
//    circlePoints.push_back({-60.5831 ,-71.2784 ,117.084});
//    circlePoints.push_back({-63.8923 ,-81.2336 ,117.79});
//    circlePoints.push_back({-68.9079 ,-96.5288 ,118.846});
//    circlePoints.push_back({-64.7816 ,-83.9722, 117.978});

    std::vector<int>circleIndex;
    double pi = acos(-1);
    for(int i=0;i<4;++i) {
        circleIndex.push_back(i);
        // circleIndex.push_back((i+1)%1000);
        double theta = 2.0/1000*i*pi;

        //circlePoints.push_back({cos(theta), sin(theta), 0});
    }


    camera = new Camera(QVector3D(0,0,0), QVector3D(-63,-78,117), width(), height());
    ourShader.addShaderFromSourceFile(QOpenGLShader::Vertex, ":/shader/model_loading.vert");
    ourShader.addShaderFromSourceFile(QOpenGLShader::Fragment, ":/shader/model_loading.frag");
    ourShader.link();


    QOpenGLVertexArrayObject::Binder bind(&VAO);
    qDebug()<<"vao id: "<< VAO.objectId();
    EBO.create();
    EBO.bind();
    EBO.allocate(circleIndex.data(), sizeof(GLint)*circleIndex.size());

    VBO.create();       //生成VBO对象
    VBO.bind();         //将VBO绑定到当前的顶点缓冲对象（QOpenGLBuffer::VertexBuffer）中
    //将顶点数据分配到VBO中，第一个参数为数据指针，第二个参数为数据的字节长度
    VBO.allocate(circlePoints.data(), sizeof(Eigen::Vector3d)*circlePoints.size());
    glVertexAttribPointer(0, 3, GL_DOUBLE, GL_FALSE, sizeof(Eigen::Vector3d), (void*)0);
    glEnableVertexAttribArray(0);

//    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8*sizeof (GLfloat), (void*)(3* sizeof(float)));
//    glEnableVertexAttribArray(1);

//    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8*sizeof (GLfloat), (void*)(6* sizeof(float)));
//    glEnableVertexAttribArray(2);

    //VAO.release();      //解绑VAO，安全使用

    texture1 = new QOpenGLTexture(QImage("D:/selfad/LearnOpenGL/resources/textures/container.jpg"));
    texture1->setWrapMode(QOpenGLTexture::Repeat);
    texture1->setMinificationFilter(QOpenGLTexture::Nearest);
    texture1->setMagnificationFilter(QOpenGLTexture::Linear);

    // QTimer::singleShot(2000, [&](){addElement();});




}

void CenterWidget::paintGL()
{
    glClearColor(0.9f, 0.8f,0.7f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    camera->DealKeyboardInputs();
    QMatrix4x4 projection;
    float w = float(width())/1000;
    float h = float(height())/1000;
    projection.ortho(-w*camera->zoom, w*camera->zoom, -h*camera->zoom, h*camera->zoom, -1000.0, 1000);
    // projection.ortho(camera->zoom, GLfloat(this->width())/GLfloat(this->height()), 0.1f, 100);
    ourShader.setUniformValue("projection",projection);
    ourShader.setUniformValue("view",camera->getViewMat());
    ourShader.setUniformValue("model",QMatrix4x4());

    emit updateGL(ourShader);
    //for(auto ele: eles)ele->Draw(ourShader);
    update();
}

void CenterWidget::resizeGL(int w, int h)
{
    // qDebug() <<"w : "<< w<< "h : "<<h;

}


void CenterWidget::keyPressEvent(QKeyEvent *event) {
    //qDebug()<<"key: down" ;
    camera->keys[event->key()]=GL_TRUE;
}

void CenterWidget::keyReleaseEvent(QKeyEvent *event) {
    //qDebug()<<"key: up" ;
    if(event->key()<0 || event->key()>=1024)return;
    camera->keys[event->key()]=GL_FALSE;
}


void CenterWidget::mousePressEvent(QMouseEvent *event){
    //qDebug()<<"mouse: down" ;
    if(event->button() == Qt::LeftButton) camera->isLeftMousePress = GL_TRUE;
}
void CenterWidget::mouseReleaseEvent(QMouseEvent *event){
    //qDebug()<<"mouse: release";
    if(event->button()==Qt::LeftButton) {
        camera->isLeftMousePress = GL_FALSE;
        camera->isFirstMouse = GL_TRUE;
    }
}
void CenterWidget::mouseMoveEvent(QMouseEvent *event){
    // qDebug()<<"mouse: move";
    GLint xpos = event->pos().x();
    GLint ypos = event->pos().y();

    if(camera->isLeftMousePress) {
        if(camera->isFirstMouse) {
            camera->lastX=xpos;
            camera->lastY = ypos;
            camera->isFirstMouse = GL_FALSE;
        }

        GLint Xoffset = xpos - camera->lastX;
        GLint Yoffset = camera->lastY - ypos;
        camera->lastX = xpos;
        camera->lastY = ypos;

        camera->DealMouseMovement(Xoffset, Yoffset);
    }
}
void CenterWidget::wheelEvent(QWheelEvent *event){
    //qDebug()<<"wheel: roll";
    QPoint offset = event->angleDelta();
    camera->DealMouseScroll(offset.y()/20.0f);
}

void CenterWidget::addElement()
{
    using namespace ELEMENT;
    qDebug()<<"add element";
    makeCurrent();
    // 加载点云
    VertexCloud *ele = new VertexCloud();
    ele->setParent(this);
    ele->setCloud("D:/selfad/alg_and_graph/3DAlgorithm/CBB3DAlgorithm/Fitting/gauss/data/b01 - 1.asc");
    eles.push_back(ele);

    VertexCloud *ele1 = new VertexCloud();
    ele1->setCloud("D:/selfad/alg_and_graph/3DAlgorithm/CBB3DAlgorithm/Fitting/gauss/data/b01.asc");
    eles.push_back(ele1);
    doneCurrent();
}
